import os
import shlex
import subprocess
import time

"""

Linux RPA Utils 说明文档


def monitor_linux_process(process_name)  -->  通过ps -ef 获取进程信息，返回所有进程信息
res = monitor_linux_process('MetricsExporter')


def get_linux_process_info(process_name)  -->  通过进程名获取进程状态
get_linux_process_info('MetricsExporter')


def start_linux_process(start_order, process_name=None, print_info=True, verification_information=None):
启动程序：
1. 获取start_order参数，在终端执行，如 start_order= './runMetricsExporter.sh start'
2. process_name:应用名称，用于判断程序是否运行在后台进程中(可选)
3. verification_information: 启动提示信息的验证信息，根据对比提示信息确定程序是否成功启动（可选）
注意：参数process_name和verification_information 两者必选一，用于判断是否启动成功
示例代码：
start_linux_process('./runMetricExporter.sh start', process_name='MetricsExporter',
                    verification_information='MetricsExporter is start success')


def close_linux_process(process_name=None, print_info=True, close_order=None, verification_information=None):
关闭程序
process_name：进程名称，通过此参数直接kill掉进程（可选）
close_order：关闭程序命令，如 close_order= './runMetricsExporter.sh stop'（可选）
verification_information： 验证信息
注意，process_name 和close_order 二者必选其一
示例代码：
close_linux_process(close_order='./runMetricExporter.sh stop',verification_information='MetricsExporter is  stoped')


重启程序：
def restart_linux_process(start_order, close_order, process_name, verification_information=None):
start_order：开启程序命令
close_order：关闭程序命令
process_name：程序名称
verification_information：验证消息
示例代码：
restart_linux_process(start_order='./runMetricExporter.sh start', process_name='MetricsExporter',
                      close_order='./runMetricExporter.sh stop',
                      verification_information='MetricsExporter is start success')

"""


class MessageStruct:
    status = None
    msg = None


def cmd_exec(cmd, timeout=10):
    """
    subprocess.Popen 方式执行cmd命令
    如果程序为cmd窗口程序，需要单独弹出一个cmd窗口，设置参数start_cmd_window=True
    """
    result = list()
    try:
        cmd_list = shlex.split(cmd)
        proc = subprocess.Popen(cmd_list, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                universal_newlines=True)
    except Exception as e:
        print(e)
        return False
    try:
        proc.wait(timeout)
    except TimeoutError as e:
        proc.terminate()
        raise TimeoutError(str(e))
    else:
        out = proc.stdout.readlines()
        for line in out:
            result.append(line.strip())
    return result


# 获取程序进程信息：pid
def monitor_linux_process(process_name):
    order = 'ps -ef | grep -w %s |grep -v grep | awk \'{print$2}\' >_tmp' % process_name
    # 进程信息输出到临时文件
    os.system(order)
    with open("_tmp", 'r', encoding='utf8') as f:
        res = f.readlines()
    os.remove('_tmp')
    return [i.strip() for i in res]


# 获取程勋进程状态
def get_linux_process_info(process_name, print_info=True):
    result = monitor_linux_process(process_name)
    if result.__len__() == 0:
        message = MessageStruct()
        message.status = '0'
        message.msg = '%s not running' % process_name
        if print_info:
            print(message.__dict__)
        return False
    else:
        # 如果存在此进程
        message = MessageStruct()
        message.status = '1'
        message.msg = '%s running,pid is ' % process_name + " ".join(result)
        if print_info:
            print(message.__dict__)
        return True


def start_linux_process(start_order, process_name=None, print_info=True, verification_information=None):
    if not process_name and not verification_information:
        message = MessageStruct()
        message.status = '0'
        message.msg = "process_name and verification_information parameters must choose one"
        print(message.__dict__)
        return False
    """

    :param start_order: 启动命令 ./runMetricExporter.sh start
    :param process_name: 程序名称，用于校验系统进程中是否存在此进程
    :param print_info:   是否打印到终端
    :param verification_information: 校验信息
    :return:
    """
    # 查看运行状态
    result = cmd_exec(start_order)
    # 是否有校验信息
    if verification_information:
        # 如果存在,使用检验信息验证是否启动成功
        for i in result:
            if i.find(verification_information) > -1:
                message = MessageStruct()
                message.status = '1'
                message.msg = "\n".join(result)
                if print_info:
                    print(message.__dict__)
                return True
            else:
                message = MessageStruct()
                message.status = '0'
                message.msg = "verification false"
                if print_info:
                    print(message.__dict__)
                return False
    else:
        # 不存在校验信息，通过进程判断程序是否启动成功
        return get_linux_process_info(process_name)


def close_linux_process(process_name=None, print_info=True, close_order=None, verification_information=None):
    """
    :param process_name: 程序名称
    :param print_info: 是否打印数据到终端
    :param close_order:  关闭程序脚本程序
    :param verification_information:
    :return:
    如果没有关闭脚本程序，则会根据程序名称杀死进程,程序名称为完全匹配，避免误杀
    """
    # 关闭程序
    # 获取程序pid
    if not process_name and not close_order:
        message = MessageStruct()
        message.status = '0'
        message.msg = "parameters error,process_name and close_order must choose one"
        print(message.__dict__)
        return False
    process_pid = monitor_linux_process(process_name)
    if close_order:  # 如果有程序关闭的脚本
        result = cmd_exec(close_order)  # 执行脚本
        if verification_information:  # 如果包含验证信息
            for i in result:
                if i.find(verification_information) > -1:  # 如果输出结果能匹配到验证信息
                    message = MessageStruct()
                    message.status = '1'
                    message.msg = "\n".join(result)
                    if print_info:
                        print(message.__dict__)
                    return True
            message = MessageStruct()  # 没有匹配到验证信息
            message.status = '0'
            message.msg = "verification false, %s process close faile"
            if print_info:
                print(message.__dict__)
            return False
        else:  # 如果不包含验证信息
            if not get_linux_process_info(process_name, print_info=False):  # 通过获取程序pid，如果没有获取到pid，证明关闭成功
                message = MessageStruct()
                message.status = '1'
                message.msg = "%s process close successful" % process_name
                if print_info:
                    print(message.__dict__)
                return True
            else:
                message = MessageStruct()
                message.status = '0'
                message.msg = "%s process close faile" % process_name
                if print_info:
                    print(message.__dict__)
                return False

    # 如果没有关闭脚本
    if len(process_pid) == 0:
        message = MessageStruct()
        message.status = '0'
        message.msg = "%s process not running" % process_name
        if print_info:
            print(message.__dict__)
        return False

    for i in process_pid:
        order = 'kill -9 %s' % i
        os.system(order)  # 使用kill 命令关闭
        print(order)

    # 再次检查pid
    pids = monitor_linux_process(process_name)
    if len(pids) == 0:
        message = MessageStruct()
        message.status = '1'
        message.msg = "%s process close successful" % process_name
        if print_info:
            print(message.__dict__)
        return True
    else:
        message = MessageStruct()
        message.status = '0'
        message.msg = "%s process close faile" % process_name
        if print_info:
            print(message.__dict__)
        return False


def restart_linux_process(start_order, close_order, process_name, verification_information=None):
    if close_linux_process(process_name=process_name, close_order=close_order, print_info=False):
        if start_linux_process(start_order, process_name, print_info=False,
                               verification_information=verification_information):
            message = MessageStruct()
            message.status = '1'
            message.msg = "%s process restart successful" % process_name
            print(message.__dict__)
            return True
    message = MessageStruct()
    message.status = '0'
    message.msg = "%s process restart faile" % process_name
    print(message.__dict__)

# start_linux_process('./runMetricExporter.sh start', process_name='MetricsExporter',
#                     verification_information='MetricsExporter is start success')
# res = monitor_linux_process('MetricsExporter')
# get_linux_process_info('MetricsExporter')
#
# close_linux_process(close_order='./runMetricExporter.sh stop',verification_information='MetricsExporter is  stoped')
# restart_linux_process(start_order='./runMetricExporter.sh start', process_name='MetricsExporter',
#                       close_order='./runMetricExporter.sh stop',
#                       verification_information='MetricsExporter is start success')
